package com.riaevolution.utils {
	import mx.styles.StyleManager;


	/**
	 * Color transformation functions.
	 * La clase ColorUtils permite crear un color (Number) partiendo de un string
	 * con la forma #FFFFFF- hexadecimal o numerica 0x342342 o rgb(255,255,255) como en CSS;
	 *
	 *
	 * <br /><b>Luciano bustos</b> <a href="mailto:luchyx&#64;riaevolution.com">luchyx&#64;riaevolution.com</a><br /><a href="http://www.riaevolution.com">www.riaevolution.com</a>
	 *
	 */
	public class ColorUtils {
		public function ColorUtils() {
		}

		private static var colorReg:RegExp = /(\d+)/i;

		private static var colorHEX:RegExp = /(\d+)x(\w{6})/i;

		/**
		 * Crea un color segun el XML de definicion segun la variable.
		 * value es un string de la forma 0xLLLLLL //siendo L una letra
		 *  o de la forma
		 * rgb(nnn,nnn,nnn) //siendo nnn un numero de 3 cifras
		 *
		 *
		 * @param value
		 * @return
		 *
		 */
		public static function createColor(value:String):Number {
			var n:Number;

			if (value == '')
				return undefined;

			if (value.indexOf("#") == 0) {
				return StyleManager.getColorName(value);
			} else if (colorHEX.test(value)) {
				n = new Number(value);
			} else {
				var cosas:Array = value.split(colorReg);
				n = RGBToHex(cosas[1], cosas[3], cosas[5]);
			}
			return n;
		}

		/**
		 * RGB to hexadecimal convertion.
		 * @param r
		 * @param g
		 * @param b
		 * @return
		 *
		 */
		public static function RGBToHex(r:Number, g:Number, b:Number):Number {
			return (r << 16 | g << 8 | b);
		}

		/**
		 * Converts a uint into a string in the format â€œ0x123456789ABCDEFâ€.
		 * This function is quite useful for displaying hex colors as text.
		 *
		 * @author Mims H. Wright (modified by Pimm Hogeling)
		 *
		 * @use <code>
		 * getNumberAsHexString(255); // 0xFF
		 * getNumberAsHexString(0xABCDEF); // 0xABCDEF
		 * getNumberAsHexString(0x00FFCC); // 0xFFCC
		 * getNumberAsHexString(0x00FFCC, 6); // 0x00FFCC
		 * getNumberAsHexString(0x00FFCC, 6, false); // 00FFCC
		 * </code>
		 *
		 *
		 * @param number The number to convert to hex. Note, numbers larger than 0xFFFFFFFF may produce unexpected results.
		 * @param minimumLength The smallest number of hexits to include in the output.
		 * 					   Missing places will be filled in with.
		 * 					   e.g. getNumberAsHexString(0xFF33, 6); // results in "0x00FF33"
		 * @param showHexDenotation If true, will append "0x" to the front of the string.
		 * @return String representation of the number as a string starting with "0x"
		 */
		public static function getNumberAsHexString(number:uint, minimumLength:uint = 1, showHexDenotation:Boolean = true):String {
			// The string that will be output at the end of the function.
			var string:String = number.toString(16).toUpperCase();

			// While the minimumLength argument is higher than the length of the string, add a leading zero.
			while (minimumLength > string.length) {
				string = "0" + string;
			}

			// Return the result with a "0x" in front of the result.
			if (showHexDenotation) {
				string = "#" + string;
			}

			return string;
		}


		/**
		 * Convert a color number to #FFFFFF hexadecimal string
		 * @param value
		 * @return  String
		 *
		 */
		public static function toHex(value:Number):String {
			if (isNaN(value))
				return "00";

			value = Math.round(Math.max(Math.min(value, 255), 0));

			var mask:String = "0123456789ABCDEF";

			var pos1:Number = (value - (value % 16)) / 16;
			var pos2:Number = value % 16;

			return mask.charAt(pos1) + mask.charAt(pos2);
		}

		/**
		 * Convierte un Hexadecimal a un Int
		 * @param value
		 * @return
		 *
		 */
		public static function hexToInt(value:String):int {
			var color:Object = fromHex(value);
			return rgb2int(color.red, color.gree, color.blue);
		}

		/**
		 * Convert a Hexadecimal color as String to RGB color info.
		 *
		 * @param value
		 * @return Object that contains  hex,red,blue,green properties.
		 *
		 */
		public static function fromHex(value:String):Object {
			if (value.indexOf("#") == 0)
				value = value.substr(1);

			while (value.length < 6)
				value = "0" + value;

			if (value.length > 6) {
				value = value.substr(0, 6);
			}
			var color:Object = {};

			color.hex = value;
			color.red = parseInt(value.substr(0, 2), 16) / 255;
			color.green = parseInt(value.substr(2, 2), 16) / 255;
			color.blue = parseInt(value.substr(4, 2), 16) / 255;
			return color;
		}

		/**
		 * Convierte un RGB a un entero
		 * @param r
		 * @param g
		 * @param b
		 * @return Number
		 */
		public static function rgb2int(r:Number, g:Number, b:Number):uint {
			return uint((Math.round(r * 255)) << 16) | uint((Math.round(g * 255)) << 8) | uint(Math.round(b * 255));
		}

		/**
		 * RGB to HSL convertion
		 *
		 * @param r
		 * @param g
		 * @param b
		 * @return
		 *
		 */
		public static function rgb2hsl(r:Number, g:Number, b:Number):Array {
			var H:Number;
			var S:Number;
			var B:Number;

			var cmax:Number = (r > g) ? r : g;

			if (b > cmax) {
				cmax = b;
			}
			var cmin:Number = (r < g) ? r : g;

			if (b < cmin) {
				cmin = b;
			}
			B = cmax;

			if (cmax != 0) {
				S = (cmax - cmin) / cmax;
			} else {
				S = 0;
			}

			if (S == 0) {
				H = 0;
			} else {
				var redc:Number = (cmax - r) / (cmax - cmin);
				var greenc:Number = (cmax - g) / (cmax - cmin);
				var bluec:Number = (cmax - b) / (cmax - cmin);

				if (r == cmax) {
					H = bluec - greenc;
				} else if (g == cmax) {
					H = 2.0 + redc - bluec;
				} else {
					H = 4.0 + greenc - redc;
				}
				H = H / 6.0;

				if (H < 0) {
					H = H + 1.0;
				}
			}
			return [H, S, B];
		}

		/**
		 * HueSaturationBlue to RGB convertion
		 *
		 * @param H
		 * @param S
		 * @param B
		 * @return
		 *
		 */
		public static function hsl2rgb(H:Number, S:Number, B:Number):Array {
			var r:Number = 0;
			var g:Number = 0;
			var b:Number = 0;

			if (S == 0) {
				r = B;
				g = r;
				b = r;
			} else {
				var h:Number = (H - Math.floor(H)) * 6.0;
				var f:Number = h - Math.floor(h);

				var p:Number = B * (1.0 - S);
				var q:Number = B * (1.0 - S * f);
				var t:Number = B * (1.0 - (S * (1.0 - f)));

				switch (Math.floor(h)) {
					case 0:
						r = B;
						g = t;
						b = p;
						break;
					case 1:
						r = q;
						g = B;
						b = p;
						break;
					case 2:
						r = p;
						g = B;
						b = t;
						break;
					case 3:
						r = p;
						g = q;
						b = B;
						break;
					case 4:
						r = t;
						g = p;
						b = B;
						break;
					case 5:
						r = B;
						g = p;
						b = q;
						break;
				}
			}
			return [r, g, b];
		}
	}
}